//  Copyright (c) 2024 Huawei Technologies Co., Ltd.
//  openUBMC is licensed under Mulan PSL v2.
//  You can use this software according to the terms and conditions of the Mulan PSL v2.
//  You may obtain a copy of Mulan PSL v2 at:
//        #  http://license.coscl.org.cn/MulanPSL2
//  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
//  EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
//  MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
//  See the Mulan PSL v2 for more details.
import { IError } from '@/model/base-interface';
import { App } from 'vue';
import { traduction } from './language';
import { ElMessage as elMessage } from 'element-plus';
import { IPREGEXV4, URL_REPLACE } from '@/utils/regular';
import { getStoreData, setStoreData } from './composition';
import HelpRelations from '@/services/help-relations.service';
import { ROUTER_BASE } from '@/model/router-utils';

// 获取获取ID
export function getMessageId(error: any): IError[] {
  if (!error) {
    return error;
  }
  const errArr: IError[] = [];
  // errors表示一个error数组，后端接口返回可能有多个错误，组合在一起形成数组
  const errors = error.error;
  if (Array.isArray(errors)) {
    errors.forEach(err => {
      const errorItem: IError = {};
      errorItem.code = err.code;
      errorItem.message = err.message;
      errorItem.relation = '';
      errArr.push(errorItem);
    });
  }

  return errArr;
}

// 针对后端返回的字符串做编码处理，预防xss攻击
export function htmlEncode(content: string): string {
  if (typeof content !== 'string') {
    return content;
  }
  if (content.length === 0) {
    return '';
  }
  let result = '';
  result = content.replace(/&/g, '&amp;');
  result = result.replace(/</g, '&lt;');
  result = result.replace(/>/g, '&gt;');
  result = result.replace(/\'/g, '&#39;');
  result = result.replace(/\"/g, '&quot;');
  return result;
}


// 字节数超最大数时，截取字符串
export function cutStr(str: string, maxLength: number): string {
  let realLength = 0;
  let charCode = -1;

  let maxIndex = str.length;
  for (let i = 0; i < str.length; i++) {
    charCode = str.charCodeAt(i);
    if (charCode >= 0 && charCode <= 127) {
      realLength += 1;
    } else if (charCode >= 128 && charCode <= 2047) {
      realLength += 2;
    } else if (charCode >= 2048 && charCode <= 65535) {
      realLength += 3;
    } else {

    }
    if (realLength > maxLength) {
      maxIndex = i;
      break;
    }
  }
  return str.substr(0, maxIndex);
}


// 获取字符串的字节长度
export function getBytes(value: string): number {
  if (typeof value !== 'string') {
    return 0;
  }
  const codeRangeArr = [
    {
      max: 127,
      min: 0,
      length: 1,
    },
    {
      max: 2047,
      min: 128,
      length: 2,
    },
    {
      max: 65535,
      min: 2048,
      length: 3,
    },
  ];
  const length = value.length;
  let charCodeLength = 0;
  for (let i = 0; i < length; i++) {
    const charCode = value.charCodeAt(i);
    codeRangeArr.forEach(item => {
      if (charCode >= item.min && charCode <= item.max) {
        charCodeLength += item.length;
      }
    });
  }
  return charCodeLength;
}

export function isIE11(): boolean {
  const userAgent = navigator.userAgent;
  const ie11Rv = /rv:([\d.]+)\) like gecko/;
  return userAgent.indexOf('Trident') > -1 && ie11Rv.test(userAgent.toLocaleLowerCase());
}

// 检查是否是Safari浏览器
export function isSafari(): boolean {
  const userAgent = navigator.userAgent;
  const result = /Safari/.test(userAgent) && !/Chrome/.test(userAgent);
  return result;
}

// 获取浏览器的类型和版本
export function getBrowserType(): { browser: string; version: number } {
  const agent = navigator.userAgent.toLowerCase();
  let version = 0;
  let browser = '';

  // Edge浏览器
  if (agent.indexOf('edge') > -1) {
    browser = 'edge';
    version = parseInt(agent.split('edge/')[1], 10);
  }

  // Firefox浏览器
  if (agent.indexOf('firefox') > -1) {
    browser = 'firefox';
    version = parseInt(agent.split('firefox/')[1], 10);
  }

  // Chrome浏览器
  if (agent.indexOf('chrome') > -1) {
    browser = 'chrome';
    const result1 = agent.match(/chrome\/\d+\.[.\d]+/);
    version = parseInt((result1 ? result1[0] : '').split('/')[1], 10);
  }

  // Safari浏览器
  if (agent.indexOf('safari') > -1 && agent.indexOf('chrome') < 0) {
    browser = 'safari';
    const result2 = agent.match(/chrome\/\d+\.[.\d]+/);
    version = parseInt((result2 ? result2[0] : '').split('/')[1], 10);
  }

  return {
    browser,
    version,
  };
}

const BROWSER_VERSION_SUPPORT = {
  firefox: 63,
  chrome: 70,
  safari: 11,
  ie: 11,
};

// 判定浏览器是否低于支持的版本
export function isLowBrowserVer(): boolean {
  const { browser, version } = getBrowserType();
  if (!BROWSER_VERSION_SUPPORT[browser] || version < BROWSER_VERSION_SUPPORT[browser]) {
    return true;
  }
  return false;
}

// 记录当前已经登录的Tab页
export function updateLocalLoginCount(type: 'add' | 'delete') {
  let tabs = parseInt(localStorage.getItem('tabs') as string);
  const tabIsValid = sessionStorage.getItem('tabIsValid');

  if (type === 'delete') {
    localStorage.setItem('tabs', JSON.stringify(0));
    sessionStorage.removeItem('tabIsValid');
  }

  if (type === 'add' && !tabIsValid) {
    tabs++;
    sessionStorage.setItem('tabIsValid', JSON.stringify(true));
    localStorage.setItem('tabs', JSON.stringify(tabs));
  }
}

// 翻译角色对应的小语种文字
export function transformRole(value: string): string {
  let result = '';
  switch (value) {
    case 'CommonUser':
    case 'Common User':
    case 'Commonuser':
      result = traduction('COMMON_ROLE_COMMONUSER');
      break;
    case 'Administrator':
      result = traduction('COMMON_ROLE_ADMINISTRATOR');
      break;
    case 'Operator':
      result = traduction('COMMON_ROLE_OPERATOR');
      break;
    case 'Custom Role 1':
    case 'CustomRole1':
      result = traduction('COMMON_ROLE_CUSTOMROLE1');
      break;
    case 'Custom Role 2':
    case 'CustomRole2':
      result = traduction('COMMON_ROLE_CUSTOMROLE2');
      break;
    case 'Custom Role 3':
    case 'CustomRole3':
      result = traduction('COMMON_ROLE_CUSTOMROLE3');
      break;
    case 'Custom Role 4':
    case 'CustomRole4':
      result = traduction('COMMON_ROLE_CUSTOMROLE4');
      break;
    case 'Custom Role 5':
    case 'CustomRole5':
      result = traduction('COMMON_ROLE_CUSTOMROLE5');
      break;
    case 'Custom Role 6':
    case 'CustomRole6':
      result = traduction('COMMON_ROLE_CUSTOMROLE6');
      break;
    case 'Custom Role 7':
    case 'CustomRole7':
      result = traduction('COMMON_ROLE_CUSTOMROLE7');
      break;
    case 'Custom Role 8':
    case 'CustomRole8':
      result = traduction('COMMON_ROLE_CUSTOMROLE8');
      break;
    case 'Custom Role 9':
    case 'CustomRole9':
      result = traduction('COMMON_ROLE_CUSTOMROLE9');
      break;
    case 'Custom Role 10':
    case 'CustomRole10':
      result = traduction('COMMON_ROLE_CUSTOMROLE10');
      break;
    case 'Custom Role 11':
    case 'CustomRole11':
      result = traduction('COMMON_ROLE_CUSTOMROLE11');
      break;
    case 'Custom Role 12':
    case 'CustomRole12':
      result = traduction('COMMON_ROLE_CUSTOMROLE12');
      break;
    case 'Custom Role 13':
    case 'CustomRole13':
      result = traduction('COMMON_ROLE_CUSTOMROLE13');
      break;
    case 'Custom Role 14':
    case 'CustomRole14':
      result = traduction('COMMON_ROLE_CUSTOMROLE14');
      break;
    case 'Custom Role 15':
    case 'CustomRole15':
      result = traduction('COMMON_ROLE_CUSTOMROLE15');
      break;
    case 'Custom Role 16':
    case 'CustomRole16':
      result = traduction('COMMON_ROLE_CUSTOMROLE16');
      break;
    case 'Noaccess':
    case 'NoAccess':
      result = traduction('COMMON_ROLE_NOACCESS');
      break;
    default:
      result = '';
  }
  return result;
}

// 转换登录规则的国际化翻译
export function getRuleText(rule: string | string[]): string | Array<string> {
  const tempRelation = {
    Rule1: 'SECURITY_SECUTITY_CFG_RULE1',
    Rule2: 'SECURITY_SECUTITY_CFG_RULE2',
    Rule3: 'SECURITY_SECUTITY_CFG_RULE3',
  };
  if (Array.isArray(rule)) {
    return rule.map(item => {
      return traduction(tempRelation[item]);
    });
  } else {
    return traduction(tempRelation[rule]);
  }
}

// 功能：数据过滤
// list：原始数据  filterKeys：过滤的字段  searchText: 过滤的条件(搜索输入框的值)
export function dataFilter(
  list: any[],
  filterKeys: string[],
  searchText?: string | '' | null,
): any[] {
  if (!searchText || !list || list.length === 0 || !filterKeys || filterKeys.length === 0) {
    return list;
  }
  let resArr: any[] = [];
  list.forEach((item: any) => {
    for (let i = 0; i < filterKeys.length; i++) {
      const value = item[filterKeys[i]];
      if (
        (value || value === 0) &&
        value.toString().toUpperCase().indexOf(searchText.toUpperCase()) >= 0
      ) {
        resArr.push(item);
        break;
      }
    }
  });
  return resArr;
}

// 功能：数组排序 (数组里面是对象，要根据对象的某个字段进行排序，而这个字段的值是中文)
// list: 原始数组  key: 要排序的字段名称  sort: 升序还是降序(1:升序，2：降序)
export function dataSort(list: any[], key: string, sort: number): any {
  if (!key || !sort) {
    return list;
  }
  // sort方法会改变原始数组，不知道使用者是否愿意更改,且在方法中没有涉及修改数组元素中的值，所以这里可以使用解构赋值进行拷贝
  let data = [...list];
  const resArr = data.sort((previousValue: any, nextValue: any) => {
    return previousValue[key] < nextValue[key] ? -1 : 1;
  });

  return sort === 1 ? resArr : resArr.reverse();
}
function compareStrings(a: string, b: string): number {
  for (let i = 0; i < Math.min(a.length, b.length); i++) {
    let charA = a[i];
    let charB = b[i];

    let codeA = charA.charCodeAt(0);
    let codeB = charB.charCodeAt(0);
    let c1 = codeA >= 65 && codeA <= 90 && codeB >= 97 && codeB <= 122;
    if (c1) {
      return -1;
    }
    let c2 = codeA >= 97 && codeA <= 122 && codeB >= 65 && codeB <= 90;
    if (c2) {
      return 1;
    }
    if (codeA !== codeB) {
      return codeA - codeB;
    }
  }
  return a.length - b.length;
}
function getKey(idx: number): number {
  let k = 1;
  if (idx !== 0) {
    k = -1;
  }
  return k;
}
function baseSort(a: any, b: any, key: string, asc: boolean): any {
  let base = asc ? 1 : -1;
  let regex = /\d+|[a-zA-Z]+/g;
  let mA = a[key].match(regex);
  let mB = b[key].match(regex);

  if (!mA || !mB) {
    return 0;
  }

  for (let i = 0; i < Math.min(mA.length, mB.length); i++) {
    let pA = mA[i];
    let pB = mB[i];

    let isNumA = /^\d+$/.test(pA);
    let isNumB = /^\d+$/.test(pB);

    if (isNumA && isNumB) {
      let numA = parseInt(pA, 10);
      let numB = parseInt(pB, 10);
      if (numA !== numB) {
        return (numA - numB) * base;
      }
    } else if (!isNumA && !isNumB) {
      let comparison = compareStrings(pA, pB);
      if (comparison !== 0) {
        return comparison * base;
      }
    } else {
      let k = getKey(i);
      return (isNumA ? -k : k) * base;
    }
  }
  return (mA.length - mB.length) * base;
}
export function dataCustomSort(arr: any, key: string, asc: boolean): any {
  return arr.sort((a: string, b: string) => {
    return baseSort(a, b, key, asc);
  });
}
// 深拷贝
export const deepClone = function clone(obj: any) {
  if (obj === null) {
    return null;
  }
  if (typeof obj !== 'object') {
    return obj;
  }

  if (obj.constructor === Date) {
    return new Date(obj);
  }

  if (obj.constructor === RegExp) {
    return new RegExp(obj);
  }

  // 保持继承链
  let newObj = new obj.constructor();
  for (let key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      // 不遍历其原型链上的属性
      const val = obj[key];
      newObj[key] = typeof val === 'object' ? clone(val) : val;
    }
  }
  return newObj;
};

// 比较两个对象是否相等
// value1、value2：比较的两个对象  exclusionsKeys：可选，要排除的字段（键）,可以是字符串，也可以是字符串数组
export function compareObjectEqual(value1: any, value2: any, exclusionsKeys?: string | string[]) {
  if (typeof value1 !== 'object' || typeof value2 !== 'object') {
    return value1 === value2;
  }

  // 如果指向同一个内存空间
  if (value1 === value2) {
    return true;
  }
  if (
    typeof value1 === 'object' &&
    value1 instanceof Object &&
    typeof value2 === 'object' &&
    value2 instanceof Object
  ) {
    const obj1 = deepClone(value1);
    const obj2 = deepClone(value2);
    // 如果有要排除的键，那么需要重新组装一下对比的数据
    if (exclusionsKeys) {
      initCompareObjs(obj1, exclusionsKeys);
      initCompareObjs(obj2, exclusionsKeys);
    }

    if (Object.keys(obj1).length !== Object.keys(obj2).length) {
      return false;
    }
    for (let key in obj1) {
      if (Object.prototype.hasOwnProperty.call(obj2, key)) {
        if (!compareObjectEqual(obj1[key], obj2[key])) {
          return false;
        }
      } else {
        return false;
      }
    }
    return true;
  } else {
    return false;
  }
}

// 加工对比数据
function initCompareObjs(value: any, exclusionsKeys: string | string[]) {
  for (let key in value) {
    if (findSameKey(key, exclusionsKeys)) {
      delete value[key];
    }
  }
}

// 查找指定的键
function findSameKey(key: string, exclusionsKeys: string | string[]) {
  if (typeof exclusionsKeys === 'string') {
    return key === exclusionsKeys;
  } else if (typeof exclusionsKeys === 'object' && exclusionsKeys instanceof Array) {
    const findItem = exclusionsKeys.find((item: string) => {
      return item === key;
    });
    if (findItem) {
      return true;
    }
    return false;
  }
  return false;
}

// 展示操作结果 type: 'info' | 'success' | 'warning' | 'error'
export function showElMessage(type: any, message: string) {
  setStoreData('event', 'alertMessage', {
    type,
    showClose: true,
    message,
  });
}

// 格式日期格式 输出的是2022/02/02 12:02:03 这种格式
export function formattingTime(time: Date) {
  if (time instanceof Date) {
    return time.toLocaleString('zh', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      hour12: false,
    });
  }
  return time;
}

export function loadComponent<T>(component: T) {
  const comp = component as any;
  comp.install = (app: App) => {
    app.component(comp.name || comp.displayname, component);
  };
  return component as T;
}

// 还原混合的IPv6完整格式
export function iPv6Translation(ipv46Arr: string[]) {
  if (ipv46Arr) {
    /**
     * 有且仅有一个空字符串，且最终这个空字符串会被替换，那么补全4位长度的字符个数就减少一位
     * 由于ipv6格式最终是8个部分，所以spacelen = 8 - (ipv46Arr.length - 1) 等价于 9 - ipv46Arr.length
     */
    const spacelen = 9 - ipv46Arr.length;
    const spaceStr = ''.padEnd(spacelen * 5, '0000:').substr(0, (spacelen * 5) - 1);
    ipv46Arr.map((item: string, i: number) => {
      if (item) {
        ipv46Arr[i] = ipv46Arr[i].padStart(4, '0');
      } else {
        // ipv6数据只有一组双冒号，所以这里只会执行一次
        ipv46Arr[i] = spaceStr;
      }
    });
    return ipv46Arr.join(':');
  } else {
    return '';
  }
}

// 将完整的IPv6地址转换成二进制字符串形式
export function convertToBinary(ipv6: string) {
  if (!ipv6) {
    return '';
  }
  const result = [];
  let res = '';
  const arr = ipv6.split(':');
  for (const key1 of arr) {
    if (IPREGEXV4.test(key1)) {
      const _arr = key1.split('.');
      for (const key2 of _arr) {
        res = Number(parseInt(key2, 10)).toString(2);
        res = res.padStart(8, '0');
        result.push(res);
      }
    } else {
      const _arrIp = key1.split('');
      for (const key3 of _arrIp) {
        res = Number(parseInt(key3, 16)).toString(2);
        res = res.padStart(4, '0');
        result.push(res);
      }
    }
  }
  return result.join('');
}

// 还原ipv6完整格式
export function restituteIpv6(ipv6: string) {
  if (typeof ipv6 !== 'string') {
    return '';
  }
  // 补全逻辑：1：将字符串由 :: 分隔，2：左侧数组和右侧数组，分别添加到临时的数据中，根据分隔出来的长度，来确定需要补全0的段数 增加补全逻辑 判断::是否在开头或者结尾
  let _temp = null;
  let tmpIPv6 = ipv6;
  if (tmpIPv6.indexOf('::') > -1) {
    const checkEndReg = /::$/;
    if (tmpIPv6.indexOf('::') === 0) {
      tmpIPv6 = `0${tmpIPv6}`;
    } else if (checkEndReg.test(tmpIPv6)) {
      tmpIPv6 = `${tmpIPv6}0`;
    } else {
      
    }
    const arr = tmpIPv6.split('::');
    let tempArr: any = [];
    tempArr = arr[0].length > 0 ? tempArr.concat(arr[0]) : tempArr;
    const len = 8 - arr[0].split(':').length - arr[1].split(':').length;
    for (let i = 0; i < len; i++) {
      tempArr.push('0000');
    }
    tempArr = arr[1].length > 0 ? tempArr.concat(arr[1]) : tempArr;
    _temp = tempArr.join(':').split(':');
  }

  // 如果没有::分隔的IP地址，则将8段数字前缀补全为0
  _temp = _temp || tmpIPv6.split(':');
  for (let j = 0; j < _temp.length; j++) {
    while (_temp[j].length < 4) {
      _temp[j] = `0${_temp[j]}`;
    }
  }
  return _temp.join(':');
}

// 初始化原始数据
export function initOriginalData(value: any, newValue?: any) {
  if (value || value === 0) {
    return value;
  } else if (newValue || newValue === 0 || newValue === '' || newValue === null) {
    return newValue;
  } else {
    return '--';
  }
}

// 根据errorCode获取SSO登录时的错误提示信息
export function getSsoErrorMsg(errorCode: number): string {
  if (typeof errorCode !== 'number') {
    return errorCode;
  }

  let result = '';
  switch (errorCode) {
    case 4096:
      result = 'LOGING_SSO_ERROR_4096';
      break;
    case 130:
      result = 'LOGING_SSO_ERROR_130';
      break;
    case 131:
      result = 'LOGING_SSO_ERROR_131';
      break;
    case 136:
      result = 'LOGING_SSO_ERROR_136';
      break;
    case 137:
      result = 'LOGING_SSO_ERROR_137';
      break;
    case 144:
      result = 'LOGING_SSO_ERROR_134';
      break;
    case 146:
      result = 'LOGING_SSO_ERROR_146';
      break;
    default:
      result = 'LOGING_SSO_ERROR_1';
  }
  return result;
}

// 打开帮助文档
export function openOnlineHelp(route: string) {
  const locale = getStoreData('loct', 'locale');
  const fileName = HelpRelations.helpRelation(route);
  let helpLocale = '';
  switch (locale) {
    case 'zh':
      helpLocale = 'zh-cn';
      break;
    case 'en':
      helpLocale = 'en-us';
      break;
    case 'ja':
      helpLocale = 'jap-ja';
      break;
    case 'fr':
      helpLocale = 'fre-fr';
      break;
    case 'ru':
      helpLocale = 'ru-ru';
      break;
    default:
      break;
  }
  const baseRouter = self.location.pathname || '/';
  window.open(`${self.location.origin}${baseRouter}help/${helpLocale}/${fileName}`);
}

// 根据颜色变量获取颜色值
export function getRealColor(val: string) {
  let res = getComputedStyle(document.body).getPropertyValue(val) || '';
  if (res) {
    // 删除所有的空格
    res = res.replace(/\s/g, '');
  }
  return res;
}

export function getThemeMode() {
  return (document.body.attributes as any).theme?.value || 'light';
}

// 获取浏览器地址栏上的参数，以对象属性的形式输出
export function getLocationSearch(search: string) {
  const temp = {};
  if (search.length > 0) {
    const param = search.substring(1);
    const paramsArr = param.split('&');
    paramsArr.forEach(item => {
      if (item === '') {
        return;
      }
      let index = item.indexOf('=');
      if (index === -1) {
        index = item.length;
      }
      const key = item.substring(0, index);
      const value = item.substring(index + 1);
      temp[key] = value;
    });
  }
  return temp;
}

// URL地址规范化, 该方法应该运行在 kvmInit之后，运行该方法前，若有数据需要通过URL传递，应改变传递方式，存储在localstorage或sessionStorage
export function urlStandardization() {
  const pathname = self.location.pathname;
  const search = self.location.search;
  const hash = self.location.hash;
  const host = self.location.host;
  if (pathname !== ROUTER_BASE || search !== '') {
    const baseRouter = ROUTER_BASE || '/';
    const url = `https://${host}${baseRouter}${hash}`;
    self.location.href = url;
  }
}

// 请求头防注入
export function escapeHeader(value?: string): string {
  if (value) {
    return value.replace(/^\w /g, '');
  } else {
    return '';
  }
}

// 编码处理和参数替换url中花括号包裹的key值，（e.g. url: url/{key}  param: {key: 123}）
export function urlReplace(url: string, param?: object): string {
  const s = url || '';
  const reg = new RegExp(URL_REPLACE);
  if (param) {
    return s.replace
      ? s.replace(reg, (match, key) => (!param[key] ? '' : encodeURIComponent(param[key])))
      : s;
  } else {
    return url;
  }
}

/**
 * @type 文本形式，可传"text/plain"纯文本
 * @filename 文件名及格式，如"data.txt"
 * @data 生成的数据
 */
export function frontDownload(type: string, filename: string, data: any) {
  let body = document.body;
  const a = document.createElement('a');
  a.href = URL.createObjectURL(
    new Blob([data], {
      type,
    }),
  );
  a.setAttribute('download', filename);
  body.appendChild(a);
  a.click();
  body.removeChild(a);
}

// 找到指定类名的子元素
export function findAimClassDom(el: Element, className: string): HTMLInputElement {
  return el.querySelector(`.${className}`) as HTMLInputElement;
}

// 找到指定标签名称的子元素
export function findAimlabelingDom(el: Element, labelingName: string): any {
  return el.getElementsByTagName(labelingName);
}

// 获取安全随机数
export function getRandomNumber(): any {
  const crypto = window.crypto || (window as any).msCrypto;
  return (crypto.getRandomValues(new Uint8Array(1)) as any) * 0.001;
}
// 对比两个对象是否完全一样， 多用于表单新旧值比较
export function deepEqual(obj1: string | object, obj2: string | object ): boolean {
  if (obj1 === obj2) {
    return true;
  }
  let condition = typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null;
  if (condition) {
    return false;
  }

  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);

  if (keys1.length !== keys2.length) {
    return false;
  }

  for (const key of keys1) {
    if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {
      return false;
    }
  }

  return true;
}

export function getDataType(obj: any): string {
  const match = Object.prototype.toString.call(obj).match(/^\[object (?<type>.*)\]$/);
  return match?.groups?.type ?? 'Unknown';
}
